#include<odb/database.hxx>
#include<odb/mysql/database.hxx>
#include"student.hxx"
#include"student-odb.hxx"
#include<gflags/gflags.h>
#include <memory>
DEFINE_string(host,"127.0.0.1","mysql host address");
DEFINE_int32(port,0,"mysql port");
DEFINE_string(db,"TestDB","mysql database 默认名称");
DEFINE_string(user,"root","mysql user name");
DEFINE_string(pswd,"123456","mysql password");
DEFINE_string(cset,"utf8","mysql charset字符集");
DEFINE_int32(max_pool,3,"mysql connection pool 最大连接数量");
void insert_classes(odb::mysql::database& db)
{
    try
    {
    //3.开启事务
    odb::transaction trans (db.begin());
    Classes c1("一班");
    Classes c2("二班");
    db.persist(c1);
    db.persist(c2);
    trans.commit();
    }
    catch(const odb::exception& e)
    {
        std::cerr<<"insert error"<<e.what()<<std::endl;
    }

}
void insert_student(odb::mysql::database& db)
{
    try
    {
     odb::transaction trans (db.begin());
    Student s1(1,"小张",18,1);
    Student s2(2,"小王",19,2);
    Student s3(3,"小李",20,1);
    Student s4(4,"小赵",21,2);
    Student s5(5,"小孙",22,1);
    db.persist(s1);
    db.persist(s2);
    db.persist(s3);
    db.persist(s4);
    db.persist(s5);

    trans.commit();
    }
    catch(const odb::exception& e)
    {
        std::cerr<<"insert error"<<e.what()<<std::endl;
    }
}
void update_student(odb::mysql::database& db,Student& s)
{
    try
    {
    odb::transaction trans (db.begin());
    //Student s1(1,"小张",14,1);
    db.update(s);
    trans.commit();
    }
    catch(const odb::exception& e)
    {
        std::cerr<<"update error"<<e.what()<<std::endl;
    }
}
Student select_student(odb::mysql::database& db)
{
    try
    {
    odb::transaction trans(db.begin());
    using query = odb::query<Student>;
    using result = odb::result<Student>;
    result r(db.query<Student>(query::name=="小张"));//这里如果没有条件，那么就是全量查询
    if(r.size()!=1)
    {
        std::cerr<<"select error"<<std::endl;
        std::exit(1);
    }
    return *r.begin();
    }
    catch(const odb::exception& e)
    {
        std::cerr<<"query error"<<e.what()<<std::endl;
    }
    return {};
}
void remove_student(odb::mysql::database& db)
{
    try
    {
     odb::transaction trans (db.begin());
     using query = odb::query<Student>;
    db.erase_query<Student>(query::classes_id ==2);//相当于delete from student where id = 1
    trans.commit();
    }
    catch(const odb::exception& e)
    {
        std::cerr<<"query error"<<e.what()<<std::endl;
    }
    
}
void classes_student(odb::mysql::database &db)
{
    try {
        //获取事务对象开启事务
        odb::transaction trans(db.begin());
        typedef odb::query<struct classes_student> query;
        typedef odb::result<struct classes_student> result;
        result r(db.query<struct classes_student>(query::classes::id==1));
        for (auto it = r.begin(); it != r.end(); ++it) {
            std::cout << it->id << std::endl;
            std::cout << it->sn << std::endl;
            std::cout << it->name << std::endl;
            std::cout << *it->age << std::endl;
            std::cout << it->classes_name << std::endl;
        }
        //5. 提交事务
        trans.commit();
    }catch (std::exception &e) {
        std::cout << "更新学生数据出错：" << e.what() << std::endl;
    }
}

void all_student(odb::mysql::database &db)
{
    try {
        //获取事务对象开启事务
        odb::transaction trans(db.begin());
        typedef odb::query<Student> query;
        typedef odb::result<struct all_name> result;
        result r(db.query<struct all_name>(query::id == 1));
        for (auto it = r.begin(); it != r.end(); ++it) {
            std::cout << it->name << std::endl;
        }
        //5. 提交事务
        trans.commit();
    }catch (std::exception &e) {
        std::cout << "查询所有学生姓名数据出错：" << e.what() << std::endl;
    }
}
int main(int argc ,char *argv[])
{
    google::ParseCommandLineFlags(&argc,&argv,true);
    //1.构造连接池工厂配置对象
    std::unique_ptr<odb::mysql::connection_pool_factory> cpf(new odb::mysql::connection_pool_factory(FLAGS_max_pool,0));
    //2.构造数据库操作对象
    odb::mysql::database db(FLAGS_user,FLAGS_pswd,FLAGS_db,FLAGS_host,FLAGS_port,"",FLAGS_cset,0,std::move(cpf));
    //3.开启事务
    std::unique_ptr<odb::mysql::transaction_impl> trans (db.begin());

    //4.数据操作
    //insert_classes(db);
    //insert_student(db);
    // auto stu = select_student(db);
    // std::cout<<stu.name()<<std::endl;
    // std::cout<<stu.age()<<std::endl;
    // stu.age(14);
    // update_student(db,stu);
    //remove_student(db);
    //classes_student(db);
    all_student(db);
    return 0;
} 